//! $Id: ContainerImpl.h 27 2011-09-16 13:28:08Z skagget77 $
//!
//! @file    ContainerImpl.h
//! @author  Johan Andersson <skagget77@gmail.com>
//! @date    Thu Oct 02 07:35 2009
//! @ingroup IoCpp
//!

#if !defined(IOCPP_CONTAINERIMPL_H)
#define IOCPP_CONTAINERIMPL_H

#include "Exception.h"
#include "IContainer.h"
#include "TypeInfo.h"

#include <boost/any.hpp>

#include <string>
#include <map>

namespace IoCpp
{
   //!
   //! @author  Johan Andersson <skagget77@gmail.com>
   //! @date    Thu Oct 02 07:35 2009
   //! @ingroup IoCppDetail
   //!
   //! The ContainerImpl class.
   //!
   class IOCPP_API ContainerImpl : public IContainer
   {
   private :
      void DoAddModule( const std::wstring& file );

      //!
      //! Adds a provider to the container.
      //!
      //! @param name The name.
      //!
      //! @param provider The provider.
      //!
      void DoAddProvider( const TypeInfo& type, const std::string& name, boost::any provider );

      //!
      //! Injects an instance of the specified type.
      //!
      //! @param  type The type.
      //!
      //! @return An instance of the specified type.
      //!
      //! @throws TypeNotFoundException When the container cannot find the type
      //!         to inject.
      //!
      //! @throws ProviderNotFoundException When the container cannot find
      //!         a provider for the type to inject.
      //!
      boost::any DoInject( const TypeInfo& type ) const;

      //!
      //! Injects an instance of the specified type.
      //!
      //! @param  type The type.
      //!
      //! @param  name The name of the instance to inject.
      //!
      //! @return An instance of the specified type.
      //!
      //! @throws TypeNotFoundException When the container cannot find the type
      //!         to inject.
      //!
      //! @throws ProviderNotFoundException When the container cannot find
      //!         a provider for the type to inject.
      //!
      boost::any DoInject( const TypeInfo& type, const std::string& name ) const;

      //!
      //! Returns the name of all provider to which the specified type is
      //! bound.
      //!
      //! @param  type The type.
      //!
      //! @return Name of all providers to which the specified type is bound.
      //!
      //! @throws TypeNotFoundException When the container cannot find the
      //!         specified type.
      //!
      ProviderNameCollection DoGetAllProviders( const TypeInfo& type ) const;

      /*!
       *
       * \param files
       * \param paths
       * \param thiz
       */
      void DoScan( const FileCollection& files, const FileCollection& optionalFiles, const PathCollection& paths, const PathCollection& optionalPaths, bool thiz );

   private :
      // Definition of a collection of named providers.
      typedef std::map<std::string,boost::any> ProviderCollection;

      // Definition of a collection of managed types.
      typedef std::map<TypeInfo,ProviderCollection> TypeCollection;

      // Collection of managed types.
      TypeCollection types;
   };
}

#endif   // IOCPP_CONTAINERIMPL_H
